﻿/*******************************************************************************
 * AAEngine
 * Copyright (c) 2010 Mike Jarosch
 *
 * Original source PushButton Engine:
 * Copyright (C) 2009 PushButton Labs, LLC
 * For more information see http://www.pushbuttonengine.com
 *
 * This file is licensed under the terms of the MIT license, which is included
 * in the "MIT License.txt" file at the root directory of this SDK.
 ******************************************************************************/

using System;
using System.Collections.Generic;

namespace AAEngine.Engine.Core
{
    /// <summary>
    /// Base implementation of a named object that can exist in AASets or AAGroups.
    /// </summary>
    public class AAObject : IAAObject
    {
        protected static int _nextId = 0;
        private AAGroup _owningGroup;
        private List<AASet> _sets;

        public int ID
        {
            get;
            protected set;
        }

        public AAGroup OwningGroup
        {
            get
            {
                return _owningGroup;
            }
            set
            {
                if (value == null)
                {
                    throw new AAException("Must always be in a group - cannot set owningGroup to null!");
                }

                if (_owningGroup != null)
                {
                    _owningGroup.RemoveFromGroup(this);
                }

                _owningGroup = value;
                _owningGroup.AddToGroup(this);
            }
        }
        public string Name
        {
            get;
            protected set;
        }

        public string Alias
        {
            get;
            protected set;
        }

        public AAObject()
        {
            ID = ++_nextId;
        }


#if WINDOWS_PHONE || XBOX
        public virtual void Initialize()
        {
            Initialize(null, null);
        }

        public virtual void Initialize(string name)
        {
            Initialize(name, null);
        }

        public virtual void Initialize(string name, string alias)
#else
        public virtual void Initialize(string name = null, string alias = null)
#endif
        {
            // Note the names.    
            Name = name;
            Alias = alias;

            // Register with the name manager.  
            AAGame.NameManager.Add(this);

            // Put us in the current group if we have no group specified.       
            if (_owningGroup == null && AAGame.CurrentGroup != this)
            {
                _owningGroup = AAGame.CurrentGroup;
            }
        }

        public virtual void Destroy()
        {
            // Remove from the name manager.
            AAGame.NameManager.Remove(this);

            // Remove from any sets.     
            while (_sets != null && _sets.Count > 0)
            {
                // remove() cuts us from the list.      
                // Note - if it returned false, we weren't in the set, so remove   
                // set membership on our end. This is usually an artifact of     
                // the set removing us from itself.              
                if (_sets[_sets.Count - 1].Remove(this) == false)
                {
                    _sets.Pop();
                }
            }

            // Remove from our owning group.        
            if (_owningGroup != null)
            {
                _owningGroup.RemoveFromGroup(this);
                _owningGroup = null;
            }
        }

        internal void ChangeName(string name)
        {
            if(!String.IsNullOrEmpty(name))
            {                
                // Remove from the name manager.            
                AAGame.NameManager.Remove(this);          
                
                // Change the name.         
                Name = name;            
                
                // Register with the name manager.     
                AAGame.NameManager.Add(this);         
            }
        }

        internal void NoteInSet(AASet set)
        {
            if (_sets == null)
            {
                _sets = new List<AASet>();
            }

            if (_sets.Contains(set))
            {
                return;
            }
            _sets.Add(set);
        }

        internal void NoteOutOfSet(AASet set)
        {
            if (_sets == null || !_sets.Contains(set))
            {
                throw new AAException("Removed object from set that it isn't in.");
            }
            _sets.Remove(set);
        }
    }
}
